/**
 * Created on 2007-03-06 13:30
 */
package game.media.gfx;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;

import manager.Manager;

/**
 * @author David Wallin
 */
public class RenderManager extends Manager
{
	/**
	 * The one instance of this class
	 */
	public static final RenderManager		INSTANCE = new RenderManager();
	
	public static final int					MATRIS_WIDTH = 14;
	public static final int					MATRIS_HEIGHT = 28;
	public static final int					MATRIS_EXTRA_WIDTH = 8;
	public static final int					GAME_AREA_OFFSET = 50;
	
	private int								m_SquareEntityWidth;
	private int								m_SquareEntityHeight;
	private int								m_GameAreaWidth;
	private int								m_GameAreaHeight;
	private int								m_InfoAreaWidth;
	private int								m_InfoAreaHeight;
	
	/**
	 * The graphics context to which to finally draw to
	 */
	private Graphics						m_Surface;
	/**
	 * The image storing the graphics context used as drawing back buffer
	 */
	private BufferedImage					m_BufferedImage;
	private Graphics						m_BackBuffer;
	private Color							m_BackgroundColor;
	private int								m_Width;
	private int								m_Height;
	private ImageObserver					m_Observer;
	
	public void setGraphicsContext(Component c)
	{
		if(c != null)
		{
			m_Surface = c.getGraphics();
			m_BackgroundColor = c.getBackground();
			m_Width = c.getWidth();
			m_Height = c.getHeight();
			
			m_SquareEntityWidth = (m_Width - GAME_AREA_OFFSET) / (MATRIS_WIDTH + MATRIS_EXTRA_WIDTH);
			m_SquareEntityHeight = m_Height / MATRIS_HEIGHT;
			//TODO make areas here for displaying text information to the player
			m_GameAreaWidth = m_SquareEntityWidth * MATRIS_WIDTH;
			m_GameAreaHeight = m_SquareEntityHeight * MATRIS_HEIGHT;
			m_InfoAreaWidth = m_SquareEntityWidth * MATRIS_EXTRA_WIDTH;
			m_InfoAreaHeight = m_SquareEntityHeight * MATRIS_HEIGHT;
			
			m_BufferedImage = new BufferedImage(m_Width, m_Height, BufferedImage.TYPE_4BYTE_ABGR);
			m_Observer = c;
		}
	}
	
	public int getSquareEntityWidth()
	{
		return m_SquareEntityWidth;
	}
	
	public int getSquareEntityHeight()
	{
		return m_SquareEntityHeight;
	}
	
	public int getGameAreaWidth()
	{
		return m_GameAreaWidth;
	}
	
	public int getGameAreaHeight()
	{
		return m_GameAreaHeight;
	}
	
	public int getInfoAreaWidth()
	{
		return m_InfoAreaWidth;
	}
	
	public int getInfoAreaHeight()
	{
		return m_InfoAreaHeight;
	}
	
	public void cls()
	{
		fillRect(0, 0, m_Width, m_Height, m_BackgroundColor);
	}
	
	public void fillRect(int x, int y, int width, int height, Color color)
	{
		if(m_BackBuffer != null)
		{
			Color oldColor = m_BackBuffer.getColor();
			
			m_BackBuffer.setColor(color);
			m_BackBuffer.fillRect(x, y, width, height);
			
			m_BackBuffer.setColor(oldColor);
		}
	}
	
	public void fillRect(int x, int y, int width, int height)
	{
		if(m_BackBuffer != null)
		{
			m_BackBuffer.fillRect(x, y, width, height);
		}
	}
	
	public void drawRect(int x, int y, int width, int height, Color color)
	{
		if(m_BackBuffer != null)
		{
			Color oldColor = m_BackBuffer.getColor();
			
			m_BackBuffer.setColor(color);
			m_BackBuffer.drawRect(x, y, width, height);
			
			m_BackBuffer.setColor(oldColor);
		}
	}
	
	public void drawRect(int x, int y, int width, int height)
	{
		if(m_BackBuffer != null)
		{
			m_BackBuffer.drawRect(x, y, width, height);
		}
	}
	
	public void drawLine(int x1, int y1, int x2, int y2, Color color)
	{
		if(m_BackBuffer != null)
		{
			Color oldColor = m_BackBuffer.getColor();
			
			m_BackBuffer.setColor(color);
			m_BackBuffer.drawLine(x1, y1, x2, y2);
			
			m_BackBuffer.setColor(oldColor);
		}
	}
	
	public void drawLine(int x1, int y1, int x2, int y2)
	{
		if(m_BackBuffer != null)
		{
			m_BackBuffer.drawLine(x1, y1, x2, y2);
		}
	}
	
	public void setCurrentFont(Font font)
	{
		if(m_BackBuffer != null)
		{
			m_BackBuffer.setFont(font);
		}
	}
	
	public void setCurrentColor(Color color)
	{
		if(m_BackBuffer != null)
		{
			m_BackBuffer.setColor(color);
		}
	}
	
	public void drawString(String str, int x, int y)
	{
		if(m_BackBuffer != null)
		{
			m_BackBuffer.drawString(str, x, y);
		}
	}
	
	public void drawString(String str, int x, int y, Font font, Color color)
	{
		if(m_BackBuffer != null)
		{
			Color oldColor = m_BackBuffer.getColor();
			Font oldFont = m_BackBuffer.getFont();
			
			m_BackBuffer.setColor(color);
			m_BackBuffer.setFont(font);
			
			m_BackBuffer.drawString(str, x, y);
			
			m_BackBuffer.setColor(oldColor);
			m_BackBuffer.setFont(oldFont);
		}
	}
	
	public void drawImage(Image img, int x, int y)
	{
		if(m_BackBuffer != null)
		{
			m_BackBuffer.drawImage(img, x, y, m_Observer);
		}
	}
	
	public void drawAnimationFrame(Image img, int destinationX, int destinationY, int sourceX, int sourceY, int sourceWidth, int sourceHeight)
	{
		if(m_BackBuffer != null)
		{
			m_BackBuffer.drawImage(img,																		//the image to draw from
					destinationX, destinationY, destinationX + sourceWidth,	destinationY + sourceHeight, 	//the destination rect's corners
					sourceX, sourceY, sourceX + sourceWidth, sourceY + sourceHeight,						//the source rect's corners
					m_Observer);																			//the image observer
		}
	}
	
	protected void doInitialize()
	{
		if(m_Surface == null)
		{
			tearDown();
		}
		else
		{
			if(m_BufferedImage != null)
			{
				m_BackBuffer = m_BufferedImage.getGraphics();
			}
		}
	}
	
	protected void doTearDown()
	{
		m_Surface = null;
		
		if(m_BufferedImage != null)
		{
			m_BufferedImage.flush();
		}
		
		if(m_BackBuffer != null)
		{
			m_BackBuffer.finalize();
		}
	}
	
	protected void doUpdate(int deltaTime)
	{
		if(m_Surface != null)
		{
			m_Surface.drawImage(m_BufferedImage, 0, 0, m_BackgroundColor, null);
		}
	}
	
	private RenderManager()
	{
		m_Surface = null;
	}
	
	public static final Font				SERIF_8_PLAIN = new Font("Serif", Font.PLAIN, 8);
	public static final Font				SERIF_10_PLAIN = new Font("Serif", Font.PLAIN, 10);
	public static final Font				SERIF_12_PLAIN = new Font("Serif", Font.PLAIN, 12);
	public static final Font				SERIF_14_PLAIN = new Font("Serif", Font.PLAIN, 14);
	public static final Font				SERIF_16_PLAIN = new Font("Serif", Font.PLAIN, 16);
	public static final Font				SERIF_18_PLAIN = new Font("Serif", Font.PLAIN, 18);
	public static final Font				SERIF_20_PLAIN = new Font("Serif", Font.PLAIN, 20);
	
	public static final Font				SERIF_8_BOLD = new Font("Serif", Font.BOLD, 8);
	public static final Font				SERIF_10_BOLD = new Font("Serif", Font.BOLD, 10);
	public static final Font				SERIF_12_BOLD = new Font("Serif", Font.BOLD, 12);
	public static final Font				SERIF_14_BOLD = new Font("Serif", Font.BOLD, 14);
	public static final Font				SERIF_16_BOLD = new Font("Serif", Font.BOLD, 16);
	public static final Font				SERIF_18_BOLD = new Font("Serif", Font.BOLD, 18);
	public static final Font				SERIF_20_BOLD = new Font("Serif", Font.BOLD, 20);
	
	public static final Font				SERIF_8_ITALIC = new Font("Serif", Font.ITALIC, 8);
	public static final Font				SERIF_10_ITALIC = new Font("Serif", Font.ITALIC, 10);
	public static final Font				SERIF_12_ITALIC = new Font("Serif", Font.ITALIC, 12);
	public static final Font				SERIF_14_ITALIC = new Font("Serif", Font.ITALIC, 14);
	public static final Font				SERIF_16_ITALIC = new Font("Serif", Font.ITALIC, 16);
	public static final Font				SERIF_18_ITALIC = new Font("Serif", Font.ITALIC, 18);
	public static final Font				SERIF_20_ITALIC = new Font("Serif", Font.ITALIC, 20);
	
	public static final Font				SANS_SERIF_8_PLAIN = new Font("SansSerif", Font.PLAIN, 8);
	public static final Font				SANS_SERIF_10_PLAIN = new Font("SansSerif", Font.PLAIN, 10);
	public static final Font				SANS_SERIF_12_PLAIN = new Font("SansSerif", Font.PLAIN, 12);
	public static final Font				SANS_SERIF_14_PLAIN = new Font("SansSerif", Font.PLAIN, 14);
	public static final Font				SANS_SERIF_16_PLAIN = new Font("SansSerif", Font.PLAIN, 16);
	public static final Font				SANS_SERIF_18_PLAIN = new Font("SansSerif", Font.PLAIN, 18);
	public static final Font				SANS_SERIF_20_PLAIN = new Font("SansSerif", Font.PLAIN, 20);
	
	public static final Font				SANS_SERIF_8_BOLD = new Font("SansSerif", Font.BOLD, 8);
	public static final Font				SANS_SERIF_10_BOLD = new Font("SansSerif", Font.BOLD, 10);
	public static final Font				SANS_SERIF_12_BOLD = new Font("SansSerif", Font.BOLD, 12);
	public static final Font				SANS_SERIF_14_BOLD = new Font("SansSerif", Font.BOLD, 14);
	public static final Font				SANS_SERIF_16_BOLD = new Font("SansSerif", Font.BOLD, 16);
	public static final Font				SANS_SERIF_18_BOLD = new Font("SansSerif", Font.BOLD, 18);
	public static final Font				SANS_SERIF_20_BOLD = new Font("SansSerif", Font.BOLD, 20);
	
	public static final Font				SANS_SERIF_8_ITALIC = new Font("SansSerif", Font.ITALIC, 8);
	public static final Font				SANS_SERIF_10_ITALIC = new Font("SansSerif", Font.ITALIC, 10);
	public static final Font				SANS_SERIF_12_ITALIC = new Font("SansSerif", Font.ITALIC, 12);
	public static final Font				SANS_SERIF_14_ITALIC = new Font("SansSerif", Font.ITALIC, 14);
	public static final Font				SANS_SERIF_16_ITALIC = new Font("SansSerif", Font.ITALIC, 16);
	public static final Font				SANS_SERIF_18_ITALIC = new Font("SansSerif", Font.ITALIC, 18);
	public static final Font				SANS_SERIF_20_ITALIC = new Font("SansSerif", Font.ITALIC, 20);
}
